<?php

namespace app\librarys;

use yii\helpers\Url;

class Tools
{
    /**
     * 获取当前系统时间(精确到毫秒)
     * @return float
     */
    public static function getMillisecond()
    {
        list($t1, $t2) = explode(' ', microtime());
        return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000);
    }

    /**
     * 获取当前系统时间(精确到微秒)
     * @return float
     */
    public static function getMicrosecond()
    {
        list($t1, $t2) = explode(' ', microtime());
        return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000000);
    }

    /**
     * 获取当前数据库时间（毫秒）
     * @return false|null|string
     */
    public static function getDbNowTime()
    {
        $sql = 'SELECT NOW(3)';
        $cmd = \Yii::$app->db->createCommand($sql);
        return $cmd->queryScalar();
    }

    /**
     * POST请求Json
     * @param string $url
     * @param mixed $data
     * @param bool $JSON_UNESCAPED_UNICODE
     * @return string
     */
    public static function postJson($url, $data, $JSON_UNESCAPED_UNICODE = false)
    {
        if ($JSON_UNESCAPED_UNICODE) {
            $data_string = json_encode($data, JSON_UNESCAPED_UNICODE);
        } else {
            $data_string = json_encode($data);
        }
        $ch = curl_init($url);
        //https 请求
        if (strlen($url) > 5 && strtolower(substr($url, 0, 5)) == 'https') {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        }

        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json',
                'Content-Length: ' . strlen($data_string),
                'charset=utf-8',)

        );

        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }

    /**
     * POST提交表单请求
     * @param string $url
     * @param mixed $data
     * @return string
     */
    public static function postForm($url, $data)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_USERAGENT, 'Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.15');
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // stop verifying certificate
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
        $result = curl_exec($curl);
        curl_close($curl);

        return $result;
    }

    /**
     * 调用系统api（已进行签名处理）
     * @param string $url
     * @param string $account
     * @param string $token
     * @param mixed $post_params
     * @param null|string $verify
     * @return string
     */
    public static function postApi($url, $account, $token, $post_params, $verify = null)
    {
        if ($verify == null) {
            $verify = self::getRandomString(8);
        }
        $timestamp = (string)time();

        $sign = strtolower(md5($account . $token . $timestamp . $verify));

        if (isset($post_params) && count($post_params) > 0) {
            Tools::arraySort($post_params);
            $post_sign = strtolower(md5(json_encode($post_params) . $token));

            $post_params['sign'] = $post_sign;
        }

        $url = $url . '?account=' . $account . '&timestamp=' . $timestamp . '&verify=' . $verify . '&sign=' . $sign;

        return self::postJson($url, $post_params);
    }

    /**
     * 获取当前站点的web根目录（自动判断index.php是否隐藏）
     * @return mixed|string
     */
    public static function urlBase()
    {
        if (\Yii::$app->urlManager->showScriptName == true) {
            $url = \Yii::$app->request->scriptUrl;
        } else {
            $url = Url::base();
        }
        return $url;
    }

    /**
     * 产生uuid（xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx）
     * @param string $prefix 前缀
     * @return string
     */
    public static function uuid($prefix = '')
    {
        $chars = md5(uniqid(mt_rand(), true));
        $uuid = substr($chars, 0, 8) . '-';
        $uuid .= substr($chars, 8, 4) . '-';
        $uuid .= substr($chars, 12, 4) . '-';
        $uuid .= substr($chars, 16, 4) . '-';
        $uuid .= substr($chars, 20, 12);
        return $prefix . $uuid;
    }

    /**
     * 产生数据库uuid
     * @return string
     */
    public static function db_uuid()
    {
        $cmd = \Yii::$app->db->createCommand("select uuid()");
        return $cmd->queryScalar();
    }

    /**
     * 获取随机字符串
     * @param int $len
     * @param string $chars
     * @return string
     */
    public static function getRandomString($len, $chars = null)
    {
        if (is_null($chars)) {
            $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        }
        for ($i = 0, $str = '', $lc = strlen($chars) - 1; $i < $len; $i++) {
            $str .= $chars[mt_rand(0, $lc)];
        }
        return $str;
    }

    /**
     * 获取完整的Exception Full Trace信息
     * @param \Exception $exception
     * @return string
     */
    public static function getExceptionFullTraceAsString($exception)
    {
        $rtn = "";
        try {
            $count = 0;
            foreach ($exception->getTrace() as $frame) {
                $args = "";
                if (isset($frame['args'])) {
                    $args = array();
                    foreach ($frame['args'] as $arg) {
                        if (is_string($arg)) {
                            $args[] = "'" . $arg . "'";
                        } elseif (is_array($arg)) {
                            $args[] = "Array";
                        } elseif (is_null($arg)) {
                            $args[] = 'NULL';
                        } elseif (is_bool($arg)) {
                            $args[] = ($arg) ? "true" : "false";
                        } elseif (is_object($arg)) {
                            $args[] = get_class($arg);
                        } elseif (is_resource($arg)) {
                            $args[] = get_resource_type($arg);
                        } else {
                            $args[] = $arg;
                        }
                    }
                    $args = join(", ", $args);
                }
                $current_file = "[internal function]";
                if (isset($frame['file'])) {
                    $current_file = $frame['file'];
                }
                $current_line = "";
                if (isset($frame['line'])) {
                    $current_line = $frame['line'];
                }
                $rtn .= sprintf("#%s %s(%s): %s(%s)\n",
                    $count,
                    $current_file,
                    $current_line,
                    $frame['function'],
                    $args);
                $count++;
            }
        } catch (\Exception $ex) {
            $rtn = $exception->getTraceAsString();
        }
        return $rtn;
    }

    /**
     * 将数组按键值由低到高排序（包含数组内部数据）
     * @param array $array
     */
    public static function arraySort(&$array)
    {
        if (!is_array($array)) {
            return;
        }

        ksort($array);
        foreach ($array as $key => &$value) {
            if (is_object($value)) {
                $value = (array)$value;
            }
            if (is_array($value)) {
                self::arraySort($value);
            }
        }
    }

    /**
     * 数组转换为对象（包含数组内数组）
     * @param array $array
     * @return mixed
     */
    public static function ArrayToObject($array)
    {
        if (is_array($array)) {
            $obj = new \stdClass();
            foreach ($array as $key => $val) {
                $obj->$key = $val;
            }
        } else {
            $obj = $array;
        }
        return $obj;
    }

    /**
     * 对象转换为数组（包含对象内的对象）
     * @param mixed $object
     * @return array
     */
    public static function ObjectToArray($object)
    {
        $array = null;
        if (is_object($object)) {
            foreach ($object as $key => $value) {
                $array[$key] = $value;
            }
        } else {
            $array = $object;
        }
        return $array;
    }

    /**
     * 验证date是否为时间格式
     * @param $date
     * @return bool
     */
    public static function checkDateIsValid($date)
    {
        if (strtotime($date)) {
            return true;
        }

        return false;

//        if (!preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}$/', $date)) {
//            return false;
//        }
//        return true;
    }

    /**
     * 转换datetime格式
     * @param string $datetime_str
     * @param string $format
     * @return false|string
     */
    public static function getDatetimeFormat($datetime_str, $format = 'Y-m-d H:i:s')
    {
        return date($format, strtotime($datetime_str));
    }


    public static function returnResult($status = 0, $message = null)
    {
        if ($status == 0) {
            return ['status' => $status, 'message' => '操作成功'];
        }

        $str = '';
        foreach ($message as $m) {
            for ($i = 0; $i < count($m); $i++) {
                $str = $str.$m[$i];
            }
        }

        return ['status' => 1, 'message' => $str];
    }
}